#include "NecPixel.h"

#define NUM_LEDS 1
#define DATA_PIN 48
CRGB leds[NUM_LEDS];

#define KEY_NUM_LEDS 29
#define KEY_led_PIN 38
CRGB keyleds[KEY_NUM_LEDS];

uint8_t colorLoop = 0;
struct ColorRGB
{
    uint8_t r;
    uint8_t g;
    uint8_t b;
};
// 混色数组
const ColorRGB myRGBColorPalette[][3] = {{{255, 255, 0}, {255, 0, 77}}, {{255, 255, 0}, {255, 0, 77}}, {{255, 255, 0}, {255, 0, 77}}};

NecPixel::NecPixel(/* args */)
{
}

NecPixel::~NecPixel()
{
}

/// @brief
/// @param
void NecPixel::init(void)
{
    FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
    FastLED.addLeds<WS2812, KEY_led_PIN, GRB>(keyleds, KEY_NUM_LEDS);
    FastLED.clear();
    FastLED.setBrightness(defBrightness);
}

void NecPixel::setBrightness(uint8_t Brightness)
{
    FastLED.setBrightness(Brightness);
}

/// @brief
/// @param n
/// @param c
void NecPixel::setPixelColor(uint16_t n, uint32_t c)
{
    if (n < KEY_NUM_LEDS)
    {
        uint8_t *p, r = (uint8_t)(c >> 16), g = (uint8_t)(c >> 8), b = (uint8_t)c;
        keyleds[n] = CRGB(r, g, b);
    }
}

/// @brief
/// @param   r  Red brightness, 0 to 255.
/// @param   g  Green brightness, 0 to 255.
/// @param   b  Blue brightness, 0 to 255.
/// @return
uint32_t NecPixel::Color(uint8_t r, uint8_t g, uint8_t b)
{
    return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}

/// @brief
/// @param hue
/// @param sat
/// @param val
/// @return
uint32_t NecPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val)
{
    uint8_t r, g, b;
    hue = (hue * 1530L + 32768) / 65536;

    if (hue < 510)
    { // Red to Green-1
        b = 0;
        if (hue < 255)
        { //   Red to Yellow-1
            r = 255;
            g = hue; //     g = 0 to 254
        }
        else
        {                  //   Yellow to Green-1
            r = 510 - hue; //     r = 255 to 1
            g = 255;
        }
    }
    else if (hue < 1020)
    { // Green to Blue-1
        r = 0;
        if (hue < 765)
        { //   Green to Cyan-1
            g = 255;
            b = hue - 510; //     b = 0 to 254
        }
        else
        {                   //   Cyan to Blue-1
            g = 1020 - hue; //     g = 255 to 1
            b = 255;
        }
    }
    else if (hue < 1530)
    { // Blue to Red-1
        g = 0;
        if (hue < 1275)
        {                   //   Blue to Magenta-1
            r = hue - 1020; //     r = 0 to 254
            b = 255;
        }
        else
        { //   Magenta to Red-1
            r = 255;
            b = 1530 - hue; //     b = 255 to 1
        }
    }
    else
    { // Last 0.5 Red (quicker than % operator)
        r = 255;
        g = b = 0;
    }

    // Apply saturation and value to R,G,B, pack into 32-bit result:
    uint32_t v1 = 1 + val;  // 1 to 256; allows >>8 instead of /255
    uint16_t s1 = 1 + sat;  // 1 to 256; same reason
    uint8_t s2 = 255 - sat; // 255 to 0
    return ((((((r * s1) >> 8) + s2) * v1) & 0xff00) << 8) |
           (((((g * s1) >> 8) + s2) * v1) & 0xff00) |
           (((((b * s1) >> 8) + s2) * v1) >> 8);
}

/// @brief 清空
void NecPixel::clear()
{
    FastLED.clear();
}

void NecPixel::clear(uint8_t value)
{
    if (value == 0)
    {
        for (size_t i = 0; i < NUM_LEDS; i++)
        {
            leds[i] = CRGB(0, 0, 0);
        }
    }
    else if (value == 1)
    {
        for (size_t i = 0; i < KEY_NUM_LEDS; i++)
        {
            keyleds[i] = CRGB(0, 0, 0);
        }
    }
    show();
}

/// @brief 绘制显示
void NecPixel::show()
{
    FastLED.show();
}

/// @brief 闪烁
void NecPixel::blink(int8_t n, int8_t Brightness)
{
    if (!(0 <= n && n < KEY_NUM_LEDS))
    {
        return;
    }
    if (!(0 <= Brightness && Brightness < 255))
    {
        return;
    }

    // keyleds[n] = CRGB(255, 255, 255);
    if (blinkstyle == 0)
        keyleds[n] = CHSV(blinkH, blinkS, Brightness * 12);
    else  if (blinkstyle == 1)
        keyleds[n] = CHSV(random(0, 255), 255, Brightness * 12);
}
/// @brief 呼吸灯
void NecPixel::Breathing()
{
    uint8_t TopBrightness = BreathingBrightnessMAX / 2;
    colorLoop += 1;
    if (colorLoop <= TopBrightness)
    {
        FastLED.setBrightness(colorLoop);
    }
    else if (TopBrightness < colorLoop && colorLoop <= BreathingBrightnessMAX - BreathingBrightnessMIN)
    {
        FastLED.setBrightness(TopBrightness - colorLoop + TopBrightness);
    }
    else
        colorLoop = BreathingBrightnessMIN;
    for (size_t i = 0; i < KEY_NUM_LEDS; i++)
    {
        setPixelColor(i, Color(255, 255, 255));
    }
}

/// @brief
void NecPixel::rainbow()
{
    colorLoop += 1;
    if (colorLoop == 60)
    {
        colorLoop = 0;
    }

    for (size_t i = 0; i < KEY_NUM_LEDS; i++)
    {
        if (colorLoop % 2 == 0)
        {

            if (i % 2 == 0)
            {
                setPixelColor(i, Color(255, 255, 0));
            }
            else
            {
                setPixelColor(i, Color(255, 0, 255));
            }
        }
        else
        {
            if (i % 2 != 0)
            {
                setPixelColor(i, Color(255, 255, 0));
            }
            else
            {
                setPixelColor(i, Color(255, 0, 255));
            }
        }
    }

    // colorLoop += 1;
    // if (colorLoop == 60)
    //{
    //     colorLoop = 0;
    // }
    //
    // for (size_t i = 0; i < KEY_NUM_LEDS; i++)
    //{
    //    setPixelColor(i, Gradient(i, 0));
    //}
}

/// @brief
void NecPixel::flicker()
{
    if (leds[0] == CRGB::Red)
    {
        leds[0] = CRGB::Blue;
        FastLED.show();
    }
    else
    {
        leds[0] = CRGB::Red;
        FastLED.show();
    }
    delay(500);
}

/// @brief
/// @param wait
void NecPixel::rainbowCycle()
{
    uint16_t i, j;

    for (j = 0; j < 256; j++)
    {
        // for (i = 0; i < KEY_NUM_LEDS; i++)
        //{
        //     setPixelColor(i, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        // }
        i = 0;
#if IShost
        /*
        24,23,15,14,6,5,
        25,22,16,13,7,4,
        26,21,17,12,8,3,
        27,20,18,11,9,2,
              19,10,
                    1,0,-1,
        */
        setPixelColor(24, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(23, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(25, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(15, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(22, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(26, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(14, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(16, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(21, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(27, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(6, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(13, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(17, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(20, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(5, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(7, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(12, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(18, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(4, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(8, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(11, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(19, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(3, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(9, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(10, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(2, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(1, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(0, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
#else
      /*5,6,14,15,23,24,
        4,7,13,16,22,25,
        3,8,12,17,21,26,
        2,9,11,18,20,27,
            10,19,
        -1,0,1,*/
        setPixelColor(24, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(23, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(25, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(15, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(22, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(26, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(14, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(16, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(21, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(27, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(6, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(13, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(17, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(20, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(5, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(7, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(12, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(18, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(4, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(8, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(11, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(19, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(3, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(9, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(10, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(2, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        setPixelColor(1, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
        setPixelColor(0, Wheel(((i * 256 / KEY_NUM_LEDS) + j) & 255));
        i++;
#endif

        show();
        delay(10);
    }
}

/// @brief 彩虹
/// @param WheelPos
/// @return
uint32_t NecPixel::Wheel(byte WheelPos)
{
    WheelPos = 255 - WheelPos;
    if (WheelPos < 85)
    {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
    }
    if (WheelPos < 170)
    {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
    }
    WheelPos -= 170;
    return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

/// @brief 渐变色颜色计算方法
/// @param index
/// @param sn
/// @return
uint32_t NecPixel::Gradient(int index, int sn)
{
    ColorRGB A = myRGBColorPalette[sn][0];
    ColorRGB B = myRGBColorPalette[sn][1];
    int n = 0;
    if (colorLoop < 31)
    {
        if (index > colorLoop)
        {
            n = index - colorLoop;
        }
        else
        {
            n = colorLoop - index;
        }
    }
    else
    {
        if (index > (colorLoop - 30))
        {
            n = 30 - (index - colorLoop + 30);
        }
        else
        {
            n = 30 - (colorLoop - 30 - index);
        }
    }
    int r = (B.r - A.r) / 30 * n + A.r;
    int g = (B.g - A.g) / 30 * n + A.g;
    int b = (B.b - A.b) / 30 * n + A.b;
    return Color(r, g, b);
}